package com.myway.components.esb;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.zip.GZIPInputStream;

import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.SecurityContext;

import org.glassfish.jersey.internal.util.Base64;

import com.myway.dto.base.ReturnMessage;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

/**
 * @ClassName: ESBClient <br/>
 * @Description: 接口调用 <br/>
 * @CreateDate: 2016年5月18日 下午2:12:38 <br/>
 * @author Toby
 * @version V1.0
 */
public class ESBClient {

	private static final String PATH = ESBConfig.getConfig(ESBEnum.path.getAlias());
	private static final String IDENTIFICATION = ESBConfig.getConfig(ESBEnum.identification.getAlias());
	private static final String FROM = ESBConfig.getConfig(ESBEnum.from.getAlias());
	private static final String NAME = ESBConfig.getConfig(ESBEnum.name.getAlias());
	private static final String PASS = ESBConfig.getConfig(ESBEnum.pass.getAlias());
	private static final String METHOD_POST = "POST";
	private static final String ENCODING_UTF8 = "UTF-8";
	private static final String CONTENT_TYPE = "text/html";
	public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss SSS";
	private static final Gson gson = new GsonBuilder().setDateFormat(DEFAULT_DATE_PATTERN).create();
	
	
	/**
	 * @Name: invoke <br/>
	 * @description:  <br/>
	 * @param en	操作ID
	 * @param obj	输入对象
	 * @param token	返回类型
	 * @return
	 */
	public static <T> T invoke(ESBEnum en,Object obj,TypeToken<T> token) throws ESBInvokeException{
		String json = gson.toJson(obj);
		return gson.fromJson(json, token.getType());
	}
	
	/**
	 * @Name: invoke <br/>
	 * @description: ESB接口调用 <br/>
	 * @param en	操作ID
	 * @param obj	输入对象
	 * @param clazz	返回类型
	 * @return
	 */
	public static <T> T invoke(ESBEnum en,Object obj,Class<T> clazz) throws ESBInvokeException{
		String json = gson.toJson(obj);
		return invoke(en, json, clazz);
	}
	
	/**
	 * @param <T>
	 * @Name: invoke <br/>
	 * @description: TODO <br/>
	 * @param en	操作ID
	 * @param json	输入json
	 * @return
	 */
	public static <T> T invoke(ESBEnum en,String json,Class<T> clazz) throws ESBInvokeException{
		String alias = en.getAlias();
		String invoke = invoke(alias,json);
		ReturnMessage returnMessage = gson.fromJson(invoke, ReturnMessage.class);
		//解决对象不是json字符串问题
		Object result = returnMessage.getResult();
		String resultJson = gson.toJson(result);
		return gson.fromJson(resultJson, clazz);
	}
	
	
	/**
	 * @Name: invoke <br/>
	 * @description:  <br/>
	 * @param en	操作ID
	 * @param json	输入json
	 * @return
	 */
	public static String invoke(ESBEnum en,String json) throws ESBInvokeException{
		String alias = en.getAlias();
		return invoke(alias,json);
	}
	
	/**
	 * @Name: invoke <br/>
	 * @description: TODO <br/>
	 * @param id		ID
	 * @param Object	输入对象
	 * @return
	 */
	public static String invoke(String id , Object Object) throws ESBInvokeException{
		String json = gson.toJson(Object);
		return invoke(id, json);
	}
	
	
	/**
	 * @Name: invoke <br/>
	 * @description: 调用ESB的方法 <br/>
	 * @param en		旧版ID
	 * @param params	参数
	 * @return
	 */
	public static String invoke(String id,String params) throws ESBInvokeException{
		try {
			ESBEnum esbEnum = ESBEnum.valueOf(id);
			String port = ESBConfig.getConfig(esbEnum.getAlias());
			if(null==port||"".equals(port)){
				throw new ESBInvokeException("没有这个端口号,或者这个端口号配置有误...");
			}
			StringBuffer realPath = new StringBuffer(PATH);
			realPath.append(port);
			realPath.append(IDENTIFICATION);
			URL url = new URL(realPath.toString());
			HttpURLConnection connection=null;
			connection = (HttpURLConnection) url.openConnection();
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setRequestMethod(METHOD_POST);
			connection.setUseCaches(false);
			String author=NAME+":"+PASS;
			connection.setRequestProperty(HttpHeaders.AUTHORIZATION, 
					"Basic "+new String(Base64.encode(author.getBytes()), ENCODING_UTF8)); 
			connection.setRequestProperty(SecurityContext.FORM_AUTH, FROM);
			connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE);
			connection.connect();
			if(connection.getRequestMethod().equals(METHOD_POST)){
				OutputStream out = connection.getOutputStream();
				Writer wout = new OutputStreamWriter(out, ENCODING_UTF8);
				wout.write(params);
				wout.flush();
				wout.close();
			}
			ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
	        GZIPInputStream gunzip = new GZIPInputStream(connection.getInputStream()); 
	        byte[] buffer = new byte[1024];
            int n; 
            while ((n = gunzip.read(buffer)) >= 0) {
            	bos.write(buffer, 0, n); 
            } 
	       	byte[] data = bos.toByteArray();
	       	String result = new String(data,ENCODING_UTF8); 
	     	return result;
		} catch (Exception e) {
			throw new ESBInvokeException(e.getMessage(),e);
		}
	}
}
